/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ca.trader.comment;

import ca.trader.beans.enterprise.CommentBeanLocal;
import ca.trader.beans.enterprise.UserBeanLocal;
import ca.trader.db.CommentTableConstraints;
import ca.trader.except.InvalidHttpRequestException;
import ca.trader.except.SaleDoesNotExistException;
import ca.trader.except.UserNotAuthenticatedException;
import ca.trader.logger.TraderLogger;
import ca.trader.user.User;
import ca.trader.utils.DebugUtils;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Ahsan
 */
@WebServlet(name = "DoCreateComment", urlPatterns =
{
	 "/DoCreateComment"
})
public class DoCreateComment extends HttpServlet
{

	 private static final String _className = DoCreateComment.class.getName();

	 private static final String PARAM_SALE_ID = "sale_id";

	 private static final String PARAM_COMMENT_STRING = "comment_string";

	 /**
	  * Reference to the UserBean EJB
	  */
	 @EJB
	 UserBeanLocal userBean;

	 @EJB
	 CommentBeanLocal commentBean;

	 /**
	  * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
	  * methods.
	  *
	  * @param request servlet request
	  * @param response servlet response
	  * @throws ServletException if a servlet-specific error occurs
	  * @throws IOException if an I/O error occurs
	  */
	 protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	 {

		  String _methodName = "processRequest";
		  response.setContentType("text/html;charset=UTF-8");

		  PrintWriter out = response.getWriter();

		  /* JSONObject for output.  will have an attribute "success" and a possible attribute "reason" as defined in the class description:
		   * The JSON object will have an attribute called "success".  The value of this is true or false.  True implies
		   * that the sale was successfully entered.  False implies it was not.
		   * For sales that were not successfully entered, a "reason" attribute is also added to the JSON string, giving the
		   * reason why the issue happened
		   */
		  JSONObject jsonObject = new JSONObject();

		  // this variable marks if the operation was successful or not
		  boolean wasSuccess = false;

		  // this varbiable marks whether a failure was unexplained (e.g. database not existing)
		  boolean wasUnexplainedFailure = false;

		  // Contains the reason for the failure if it happens (explained or unexplained)
		  String failureReason = "";

		  // Incase the failure is unexplained, this will contain the stack trace of the failure
		  String unexplainedFailureReasonStackTrace = "";

		  try
		  {

			   TraderLogger.logInfo(_className, _methodName, "Starting servlet: " + this.getServletName());

			   TraderLogger.logInfo(_className, _methodName, "Validating POST parameters");

			   // Validate the request.  This function will throw an exception if there's an issue
			   validateRequest(request);

			   // Get the sale title
			   Integer saleID = Integer.parseInt(request.getParameter(PARAM_SALE_ID).trim());

			   // Get the sale description
			   String commentString = request.getParameter(PARAM_COMMENT_STRING).trim();

			   TraderLogger.logInfo(_className, _methodName, "Fetching authenticated user from DB");

			   // Get the authenticated user via the user bean
			   User user = userBean.getAuthenticatedUser(request.getSession());

			   commentBean.insertComment(user, saleID, commentString);

			   TraderLogger.logInfo(_className, _methodName, String.format("Inserted the comment into the DB.  Commentor ID = %d, Sale ID = %s", user.getId(), saleID));

			   wasSuccess = true;

		  }
		  catch (InvalidHttpRequestException | SaleDoesNotExistException ex)
		  {
			   wasSuccess = false;
			   failureReason = ex.getMessage();
		  }
		  /**
		   * If there is no authenticated user
		   */
		  catch (UserNotAuthenticatedException e)
		  {
			   wasSuccess = false;
			   failureReason = "No user is not logged in.  Please log in and try again";
		  }
		  /**
		   * Unexplained failure
		   */
		  catch (Exception e)
		  {
			   wasSuccess = false;
			   failureReason = "Unknown error: " + e.getMessage();

			   wasUnexplainedFailure = true;
			   unexplainedFailureReasonStackTrace = DebugUtils.getStackTraceAsString(e);

		  }
		  finally
		  {
			   // If the failure was unexplained, log it
			   if (wasUnexplainedFailure)
			   {
				    TraderLogger.logSevere(_className, _methodName, failureReason, unexplainedFailureReasonStackTrace);
			   }

			   try
			   {
				    // add the success attribute to the jsonObject
				    jsonObject.put("success", wasSuccess);

				    // if the request was not successful, put the reason in the jsonObject
				    if (!wasSuccess)
				    {
						jsonObject.put("reason", failureReason);
						TraderLogger.logInfo(_className, _methodName, "Unable to create comment: " + failureReason);
				    }

				    // print the jsonObject
				    out.print(jsonObject.toString());
			   }
			   catch (JSONException ex)
			   {
			   }

			   TraderLogger.logInfo(_className, _methodName, "Exiting servlet: " + this.getServletName());

		  }
	 }

	 // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
	 /**
	  * Handles the HTTP <code>GET</code> method.
	  *
	  * @param request servlet request
	  * @param response servlet response
	  * @throws ServletException if a servlet-specific error occurs
	  * @throws IOException if an I/O error occurs
	  */
	 @Override
	 protected void doGet(HttpServletRequest request, HttpServletResponse response)
		    throws ServletException, IOException
	 {
		  processRequest(request, response);
	 }

	 /**
	  * Handles the HTTP <code>POST</code> method.
	  *
	  * @param request servlet request
	  * @param response servlet response
	  * @throws ServletException if a servlet-specific error occurs
	  * @throws IOException if an I/O error occurs
	  */
	 @Override
	 protected void doPost(HttpServletRequest request, HttpServletResponse response)
		    throws ServletException, IOException
	 {
		  processRequest(request, response);
	 }

	 /**
	  * Returns a short description of the servlet.
	  *
	  * @return a String containing servlet description
	  */
	 @Override
	 public String getServletInfo()
	 {
		  return "Short description";
	 }// </editor-fold>

	 /**
	  * Validates the servlet request
	  *
	  * @param request the servlet request
	  * @throws InvalidHttpRequestException if there is an issue with the
	  * servlet request
	  */
	 private static void validateRequest(HttpServletRequest request) throws InvalidHttpRequestException
	 {
		  if (request.getParameter(PARAM_SALE_ID) == null || request.getParameter(PARAM_COMMENT_STRING) == null)
		  {
			   throw new InvalidHttpRequestException(String.format("One of the following parameters does not exist: %s, %s", PARAM_SALE_ID, PARAM_COMMENT_STRING));
		  }

		  String commentString = request.getParameter(PARAM_COMMENT_STRING).trim();

		  if (commentString.length() > CommentTableConstraints.CONSTRAINT_COMMENT_MAX_LENGTH)
		  {
			   throw new InvalidHttpRequestException("Comment string must be a maximum of " + CommentTableConstraints.CONSTRAINT_COMMENT_MAX_LENGTH + " characters long.");
		  }

		  try
		  {
			   Integer.parseInt(request.getParameter(PARAM_SALE_ID));
		  }
		  catch (NumberFormatException nfe)
		  {
			   throw new InvalidHttpRequestException("Sale ID must be an integer");
		  }
	 }

}
